//
// Created by 17775 on 2024/6/24.
//

#ifndef RAYCI_LIVEMODE_OPTIONS_H
#define RAYCI_LIVEMODE_OPTIONS_H

#include "../utils/LiveModeOptionsListener.h"
#include "../RayCi/LiveMode.h"
#include "../Device_Motor_Panel/Motor_Control_Panel.h"


QT_BEGIN_NAMESPACE
namespace Ui { class LiveMode_Options; }
QT_END_NAMESPACE

enum class Spatial_Unit{
    px,
    um,
    mm,
    cm,
    in,
    m
};

class LiveMode_Options : public QDockWidget, public LiveModeOptionsListener {
Q_OBJECT

public:

    LiveMode_Analysis *liveModeAnalysis = nullptr;
    explicit LiveMode_Options(QWidget *parent = nullptr);
    ~LiveMode_Options() override;
    void setWindowTitleName(const QString& name);

    Motor_Control_Panel *motorControlPanel = nullptr;
    void receiveMessage(const std::shared_ptr<int>& msg) override;
    int getOrder() const override {
        return 100;
    }

    void initAfterConnectLiveMode() const;
    void changeLiveModeOptions(int index) const;
    void setCamExposureTimeList(const std::vector<double>& _vecExposureTimes) const;
    void updateControl(bool isExposureTimeAutomatic) const;
    void updatePixelSizeInfo(double dPixelSizeX, double dPixelSizeY) const;
    void updateWavelength(double wavelength) const;
    void updateFocalLength(double wavelength) const;
    void exposureTimeIndexChanged();
    void gainIndexChanged();
    void binningIndexChanged();
    void exposureTimeAutoChanged();
    void gainAutoChanged();
    void reducePixelClockChanged();
    void queryAutoExposureTime();
    int  getExposureTimeMeasureCount() const;
    void updateThresholdValue();
    void updateSigmaEnvironment();
    void updateFraction();
    void updateSigma();
    void updateThreshold();
    void updatePowerFraction();
    void calculateSlopeClicked();
    MethodsType methods;
    void setMeasurePosition(double  pos) const;
    void setMaxFrameRate(double max) const;
    void setMinFrameRate(double min) const;
    void setFrameRate(double rate) const;
    void setTimeSpan(int index) const;
    void setControlExposureTime(int index) const;
    void setControlGainAndBinning(int GainIndex,int Binning) const;

    double getXPixelSize() const;
    double getYPixelSize() const;
    double getManualBeamQualityPosition() const;
    //BackGround Correction

    void setBackGroundProgress(int index, int proportion, int frame, double durationtime) const;
    void setInitBackGroundButton(bool canload,bool cansave,bool canclear);
    void backgroundMeasuring(bool measuring) const;
    void BackGroundIsMeasured(const bool  isMeasured) const;


    //Time Series
    void setMinLabel(double min) const;
    void setFramesLabel(int times, int frames) const;
    void setDurationLabel(int times, double timeSpan) const;
    void setDelayTimeMin(double delayTimeMin) const;
    void setTimeSeriesRemark(const QString& remark) const;
    double getCurrentDelay() const;
    void addTimeSeriesSequenceItem(const QString &info) const;
    void clearTimeSeriesTableWidget() const;

    // Divergence
    static int divergenceFileCount;
    void startDivergenceUI();
    void endDivergenceUI();
    void setDivergenceFramesLabel(int frames) const;
    void setDivergenceDurationLabel(double timeSpan) const;
    void setDivergenceRemark(const QString& remark) const;
    void addDivergenceSequenceItem(const QString &info) const;
    void clearDivergenceTableWidget() const;


    // Beam Line
    static int beamLineFileCount;
    void startBeamLineUI();
    void endBeamLineUI();
    void setBeamLineFramesLabel(int frames) const;
    void setBeamLineDurationLabel(double timeSpan) const;
    void setBeamLineRemark(const QString& remark) const;
    void addBeamLineSequenceItem(const QString &info) const;
    void clearBeamLineTableWidget() const;

    // Beam Quality
    static int beamQualityFileCount;
    void setLiveModeAnalysis(LiveMode_Analysis* a);
    void startBeamQualityUI();
    void endBeamQualityUI();
    void initBeamQualityUI();
    void setBeamQualityFramesLabel(int frames) const;
    void setBeamQualityDurationLabel(double timeSpan) const;
    void setBeamQualityRemark(const QString& remark) const;
    void addBeamQualitySequenceItem(const QString &info,int beamQualityIndex,bool checked) const;
    void onBeamQualitySequenceRemoveClicked();
    void BeamQualitySequenceswapRows(int row1, int row2);
    void onBeamQualitySequenceMoveUpClicked();
    void onBeamQualitySequenceMoveDownClicked();
    void onBeamQualitySequenceSortClicked();
    void onBeamQualitySequenceRefreshClicked();
    void onBeamQualitySequenceRefreshed(const QVector<QString> &vec, const QVector<bool> &vecChecked);
    // void setTimeSeriesSequence(int time,int frame,int proportion);
    void clearBeamQualityTableWidget() const;
    void connectMotor();
    void setBeamQualityProgress(int time, int frame, int proportion,bool IsFrameSpan);
    void setBeamQualityMeasureMethod(int methodIndex);
    void setRawBeamBeamQualityMeasureResult(bool isRawBeam);
    int BeamQualityFrame;

    // Beam Stability
    void startBeamStabilityUI();
    void endBeamStabilityUI();
    void setBeamStabilityFramesLabel(int frames) const;
    void setBeamStabilityDurationLabel(double timeSpan) const;

    // Pointing Stability
    void startPointingStabilityUI();
    void endPointingStabilityUI();
    void setPointingStabilityFramesLabel(int frames) const;
    void setPointingStabilityDurationLabel(double timeSpan) const;



signals:
    void openLiveMode();
    void setExposureTime(int index);
    void setGain(int index);
    void setBinning(int index);

    void setAutoExposureTime(bool autoExposure);
    void setAutoGain(bool autoGain);
    void setReducePixelClock(bool reducePixelClock);
    void queryControl();
    void setMethods(MethodsType methods, bool bFitGaussSigma, int sigmaIndex, int thresholdIndex, int fractionIndex);
    void setSingleMethods(MethodsType methods, bool bfitGaussSigma, int sigmaIndex, int thresholdIndex, int fractionIndex);
    void setUnit(QString unit);
    void setSpatialManually(bool manual, double dSizeX, double dSizeY);
    void setPowerManually(bool manual);
    void setDivergenceActive(bool active);
    void changeThresholdValue(MethodsType methods, int index);
    void changeSigmaEnvironment(MethodsType method, int index);
    void changeFraction(MethodsType method, int index);
    void sigmaChanged(int sigmaIndex);
    void sigmaIsChecked(int sigmaIndex);
    void thresholdIsChecked(int thresholdIndex);
    void thresholdChanged(int thresholdIndex);
    void powerFractionIsChecked(int fractionIndex);
    void powerFractionChanged(int fractionIndex);
    void calculateSlopeChanged(MethodsType method, bool slopeIsChecked);

    // Background
    void setBackgroundFrameSpan(int frames);
    void setBackgroundTimeSpan(double time);
    void setBackgroundCurrentExposure();
    void setBackgroundAllExposure();
    void startBackgroundMeasurement();
    void stopBackgroundMeasurement();
    void loadBackground();
    void saveBackground();
    void clearBackground();

    // Single
    void setSingleFrameSpan(int frames);
    void setSingleTimeSpan(double time);
    void startSingleMeasurement();
    void stopSingleMeasurement();

    // Time Series
    void startTimeSeriesMeasurement();
    void stopTimeSeriesMeasurement();
    void clearTimeSeriesMeasurement();
    void showRowItemImage(int row);
    void setRunning(bool clicked);
    void setMeasurementTimes(int value);
    void setDelayTime(double delayTime);
    void setMedianFilter(bool bMedian);
    void setSingleMedianFilter(bool bMedian);
    void setTimeSeriesFramesSpan(int frames);
    void setTimeSeriesTimeSpan(double time);

    // Divergence
    void startDivergenceMeasurement();
    void stopDivergenceMeasurement();
    void clearDivergenceMeasurement();
    void setDivergenceFramesSpan(int frames);
    void setDivergenceTimeSpan(int times);
    void setDivergencePosition(double pos);
    void showDivergenceImage(int row);

    // Beam Line
    void startBeamLineMeasurement();
    void stopBeamLineMeasurement();
    void clearBeamLineMeasurement();
    void setBeamLineFramesSpan(int frames);
    void setBeamLineTimeSpan(int times);
    void showBeamLineImage(int row);

    // Beam Quality
    void startBeamQualityMeasurement();
    void stopBeamQualityMeasurement();
    void clearBeamQualityMeasurement();
    void setBeamQualityFramesSpan(int frames);
    void setBeamQualityTimeSpan(int times);
    void showBeamQualityImage(int row);
    void recalibrateBeamQualityFocalLength(double position);
    void ResultshowISO_1();
    void ResultshowISO_2();
    void ResultshowDetails();
    void BeamQualityRawBeam(bool isRawBeam);
    void beamqualitysequence_add() const;
    void beamqualitysequence_remove(int index);
    void beamqualitysequence_moveup(int index);
    void beamqualitysequence_movedown(int index);
    void beamqualitysequence_itemChecked(int index,bool checked);
    void beamqualitysequence_sort();
    void beamqualitysequence_refreshed();

    // Beam Stability
    void startBeamStabilityMeasurement();
    void stopBeamStabilityMeasurement();
    void setBeamStabilityFramesSpan(int frames);
    void setBeamStabilityTimeSpan(double time);
    void setBeamStabilityTimeStep(double time);

    // Pointing Stability
    void startPointingStabilityMeasurement();
    void stopPointingStabilityMeasurement();
    void setPointingStabilityFramesSpan(int frames);
    void setPointingStabilityTimeSpan(double time);
    void setPointingStabilityTimeStep(double time);

    void startSemiAutoBeamQualityMeasurement();
    void startAutoBeamQualityMeasurement();

    // Motor Control
    void motorPositionChanged(double position,bool isshow=true);
    inline bool isMotorConnected() const;

public slots:
    void updateBeamWidthSettings();
    void updateSingleBeamWidthSettings();
    void updateSpatialUnit(const QAbstractButton *checkedButton);
    void ManullyUpdataPixelSize();
    void updateCheckBoxSettings(const QAbstractButton *checkedButton);
    void performBackgroundCalibration();

    void updateFrameNum(const QString& frameNum, const QString& sTime, int nSizeX, int nSizeY, const QString& colorFormat, int bitDepth) const;
    void updateSelectionInfo(const QString& accessory, double floatingAverage, int summing) const;
    void updateCamInfo(const std::vector<sCameraItem> &m_vecCameras) const;
    void updateSetting(LiveMode *rayCi) const;
    void closeOptions() const;
    void handleMotorPositionChanged(double position,bool isshow=true);
private:
    Ui::LiveMode_Options *ui;
    QButtonGroup *methodButtonGroup = nullptr;
    QButtonGroup *single_MethodButtonGroup = nullptr;
    QButtonGroup *unitButtonGroup = nullptr;
    QButtonGroup *checkBoxGroup = nullptr;
    QButtonGroup *backgroundGroup = nullptr;

    void btn_Live_Mode_Clicked();
    static double getDuration(int index);
    static double getBeamStabilityDuration(int index);
    void initBeamWidthSettingsValue() const;
    void initCorrectionsBackground() const;
    void initSingleMeasurementOption() const;
    void initTimeSeries() const;
    void initDivergence() const;
    void initBeamLine() const;
    void initBeamQuality() const;
    void initBeamStability() const;
    void initPointingStability() const;
    void initCorrectionsBaseline() const;
    void initUnitsSettings() const;
    void initControlSettings() const;
};

#endif //RAYCI_LIVEMODE_OPTIONS_H
